package com.kaikeba.estack.dao.imp;

import com.google.common.collect.ImmutableMap;
import com.kaikeba.estack.common.jdbc.DataSourceUtil;
import com.kaikeba.estack.common.jdbc.JdbcUtil;
import com.kaikeba.estack.exception.DataAccessException;
import com.kaikeba.estack.common.util.GenericsUtils;
import com.kaikeba.estack.dao.BaseDao;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * 通用的工具dao
 *
 * @Auth xingwan
 * @Date 2020/9/12 17:27
 **/
public abstract class BaseDaoImpl<T> implements BaseDao<T> {

    private Class<T> tClass = GenericsUtils.getSuperClassGenericType(this.getClass());

    private String deleteSql = buildDeleteSql();

    private String buildDeleteSql() {
        return "delete from " + getTableName() + " where id = :id";
    }

    private String selectSql = buildSelectSql();

    private String buildSelectSql() {
        return "select * from " + getTableName() + " where is_del = 0";
    }

    private String selectCountSql = buildSelectCountSql();

    private String buildSelectCountSql() {
        return "select count(1) from " + getTableName() + " where is_del = 0";
    }

    @Override
    public void insert(String sql, Map<String, Object> params) {
        execute(sql, params);
    }

    @Override
    public boolean update(String sql, Map<String, Object> params) {
        return execute(sql, params);
    }

    @Override
    public boolean delete(Serializable id) {
        return execute(deleteSql, ImmutableMap.of("id", id));
    }

    @Override
    public boolean delete(String sql, Map<String, Object> params) {
        return execute(sql, params);
    }

    @Override
    public List<T> listAll() {
        return list(selectSql, null);
    }

    @Override
    public List<T> list(String sql, Map<String, Object> params) {
        assert StringUtils.isBlank(sql) : new DataAccessException("sql is black");
        try {
            return JdbcUtil.queryForList(DataSourceUtil.getConnection(), sql, tClass, params);
        } catch (SQLException sqlException) {
            throw new DataAccessException(sqlException);
        }
    }

    @Override
    public long count() {
        return count(selectCountSql, null);
    }

    @Override
    public long count(String sql, Map<String, Object> params) {
        assert StringUtils.isBlank(sql) : new DataAccessException("sql is black");
        try {
            return JdbcUtil.queryForObject(DataSourceUtil.getConnection(), sql, Long.class, params);
        } catch (SQLException sqlException) {
            throw new DataAccessException(sqlException);
        }
    }

    protected boolean execute(String sql, Map<String, Object> params) {
        assert StringUtils.isBlank(sql) : new DataAccessException("sql is black");
        try {
            int rows = JdbcUtil.execute(DataSourceUtil.getConnection(), sql, params);
            return rows > 0;
        } catch (SQLException sqlException) {
            throw new DataAccessException(sqlException);
        }
    }

    @Override
    public T find(String sql, Map<String, Object> params) {
        assert StringUtils.isBlank(sql) : new DataAccessException("sql is black");
        try {
            return JdbcUtil.queryForObject(DataSourceUtil.getConnection(), sql, tClass, params);
        } catch (SQLException sqlException) {
            throw new DataAccessException(sqlException);
        }
    }
}
